/*
 * TimerServicer.cpp
 *
 *   This is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2 of the License, or (at your option) any later version.
 *
 *   This software is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Lesser General Public License for more details.
 *
 *  Created on: 2010-1-2
 *      Author: Huang Haiyang
 */

#include "../TimerService.h"

namespace service
	{

	TimerService::TimerService(OnTickListener* aListener)
		:iOnTickListener(aListener)
		{

		}

	TimerService::~TimerService()
		{
		Kill();
		}

	void TimerService::Start()
		{
		iRuning = ETrue;
		ElapseBeat();
		}
	
	TUint32 TimerService::Next()
		{
		Synchronize();
		return iTimeInMills;
		}
	
	void TimerService::Stop()
		{
		iRuning = EFalse;
		Kill();
		}
	
	void TimerService::Reset()
		{
		Stop();
		iTimeInMills = 0;
		}
			
	void TimerService::Beat()
		{
		Synchronize();
		if (iOnTickListener)
			{
			iOnTickListener->OnTick(iTimeInMills);
			}
		}
	
	void TimerService::Synchronize()
		{
		TUint32 currentTickCount = iClockSource.Ticks();
		iTimeInMills += ((currentTickCount - iLastTickCount) * iClockSource.TickPeriod()) / 1000; 
		iLastTickCount = currentTickCount;				
		}
			
	void TimerService::ElapseBeat()
		{
		if (!iHeartbeat)
			{
			iHeartbeat = CPeriodic::New(EPriorityLow);
			}
		
		if (iHeartbeat->IsActive())
			{
			iHeartbeat->Cancel();
			}
		iHeartbeat->Start(0, 1000*50, TCallBack(doTick, this));
		iLastTickCount = iClockSource.Ticks();
		}
	
	void TimerService::Kill()
		{
		if (iHeartbeat)
			{
			iHeartbeat->Cancel();
			delete iHeartbeat;
			iHeartbeat = NULL;
			}
		}
	
	TInt TimerService::doTick(TAny* aCtx)
		{
		TimerService* self = (TimerService*)aCtx;
		self->Beat();
		return 0;
		}
	}
